﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="EventBinder_When_From.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Defines the EventBinder_When_From type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Threading
{
    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Mocks;
    using EventPattern;
    using Testing;

    [TestClass]
   public class EventBinder_When_From : EventBinder_When_Base
   {
      public static readonly Action<object, EventHandler<EventArgs>> NullHandler = null;
      public static readonly Action<object, EventHandler<EventArgs>> MockHandler = (o, h) => 
         MockDelegates.DoNothing();

      [TestMethod]
      public void If_EventInfo_Is_Null_Should_Throw_ArgumentNullException()
      {
         new MethodTest(() => EventBinder<EventArgs>.From(null))
            .AssertThrowsArgumentNullException(0);
      }

      [TestMethod]
      public void If_Type_Is_Null_Should_Throw_ArgumentNullException()
      {
         new MethodTest(() => EventBinder<EventArgs>.From(null, "Test"))
            .AssertThrowsArgumentNullException(0);
      }

      [TestMethod]
      public void If_EventName_Is_Null_Should_Throw_ArgumentNullException()
      {
         new MethodTest(() => EventBinder<EventArgs>.From(typeof (object), null))
            .AssertThrowsArgumentNullException(1);
      }

      [TestMethod]
      public void If_AddHandler_Is_Null_Should_Throw_ArgumentNullException()
      {
         new MethodTest(() => EventBinder<EventArgs>.From(NullHandler, MockHandler))
            .AssertThrowsArgumentNullException(0);
      }

      [TestMethod]
      public void If_RemoveHandler_Is_Null_Should_Throw_ArgumentNullException()
      {
         new MethodTest(() => EventBinder<EventArgs>.From(MockHandler, NullHandler))
            .AssertThrowsArgumentNullException(1);
      }

      [TestMethod]
      public void If_EventName_Is_Not_Found_Should_Throw_ArgumentOutOfRangeException()
      {
         new MethodTest(() => EventBinder<EventArgs>.From(typeof (object), "BadEventName"))
            .AssertThrowsArgumentOutOrRangeException("BadEventName", 1);
      }

      [TestMethod]
      public void If_Type_And_EventName_Are_Valid_Should_Return_Binder()
      {
         var binder = EventBinder<EventArgs>.From(typeof (TestEventSource), "Fired");
         Assert.IsNotNull(binder);
      }

      [TestMethod]
      public void If_Handler_Has_Been_Added_Should_Start_Receiving_Events()
      {
         var firedCount = 0;
         var source = new TestEventSource();
         var binder = EventBinder<EventArgs>.From(source.GetType(), "Fired");
         binder.AddHandler(source, (s, e) => firedCount++);
         
         Assert.AreEqual(0, firedCount);
         source.Fire();
         Assert.AreEqual(1, firedCount);
      }

      [TestMethod]
      public void If_Handler_Has_Been_Removed_Should_Stop_Receiving_Events()
      {
         var firedCount = 0;
         var source = new TestEventSource();
         var binder = EventBinder<EventArgs>.From(source.GetType(), "Fired");
         EventHandler<EventArgs> handler = (s, e) => firedCount++;

         // add handler and verify we recieve events
         binder.AddHandler(source, handler);
         Assert.AreEqual(0, firedCount);
         source.Fire();
         Assert.AreEqual(1, firedCount);

         // remove handler and verify we no longer recieve events
         binder.RemoveHandler(source, handler);
         source.Fire();
         Assert.AreEqual(1, firedCount);
      }
   }
}
